
/* Threads safe. FIFO queue. */

#include "common.h"

queue_t * queue_create(void)
{
	queue_t *q = mempool_alloc(sizeof(*q));
	if(!q) 
		return q;
	
	pthread_cond_init(&q->cond, NULL);
	pthread_mutex_init(&q->lock, NULL);
	INIT_LIST_HEAD(&q->list);

	return q;
}

void queue_push(queue_t *queue, queue_item_t *item)
{
	if(!queue) 
		return;
	if(!item)
		return;

	pthread_mutex_lock(&queue->lock);
	list_add_tail(&item->list, &queue->list);
	queue->count++;
	pthread_cond_signal(&queue->cond);
	pthread_mutex_unlock(&queue->lock);
}


struct list_head *queue_pop(queue_t *queue, struct list_head *new_head)
{
	if(!queue) 
		return NULL;
	
	if(list_empty(&queue->list))  
		return NULL;
	
	pthread_mutex_lock(&queue->lock);
	while(list_empty(&queue->list)) 
		pthread_cond_wait(&queue->cond, &queue->lock);

	list_add(new_head, &queue->list);
	list_del_init(&queue->list);
	queue->count = 0;
	pthread_mutex_unlock(&queue->lock);

	return new_head;
}

queue_item_t *queue_item_get(queue_t *queue, int pos)
{
	if(!queue) 
		return NULL;
	
	
	pthread_mutex_lock(&queue->lock);

	queue_item_t *retv;
	struct list_head *cur = &queue->list;
	struct list_head *p;
	list_for_each(p, cur) {
		retv = list_entry(p, queue_item_t, list);
	}
	
	pthread_mutex_unlock(&queue->lock);

	return retv;
}

void queue_destroy(queue_t *queue)
{
	if(!queue)
		return;

	pthread_cond_destroy(&queue->cond);
	pthread_mutex_destroy(&queue->lock);

	mempool_free(queue);
}

queue_item_t * queue_item_init(void *data)
{
	queue_item_t *it = mempool_alloc(sizeof(*it));
	assert(it);
	
	it->node = data;
	INIT_LIST_HEAD(&it->list);

	return it;
}

void queue_item_free(queue_item_t *it)
{
	if(!it) 
		return;

	mempool_free(it);
}
